package com.whc.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.whc.constant.JwtClaimsConstant;
import com.whc.constant.RedisHeader;
import com.whc.context.BaseContext;
import com.whc.properties.JwtProperties;
import com.whc.utils.JwtUtil;
import com.whc.vo.SecurityUser;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

/**
 * @author 韦红材
 * @ClassName JwtAuthenticationTokenFilter
 * @data 2024/12/22 14:10
 * @Version V1.0
 **/
@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    //目的是过滤请求，拿到请求中的认证信息，把他存入SecurityContextHolder,方便后期security的那些拦截器获取
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {


        //获取token
        String token = request.getHeader(jwtProperties.getUserTokenName());
        //为空不再处理下面的，并且放行，因为拿不到认证信息
        if(token==null||"".equals(token)){
            filterChain.doFilter(request,response);
            return;
        }
        //解析token获取其中的userId
        String userid="";
        try{
            log.info("校验令牌");
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
             userid = claims.get(JwtClaimsConstant.USER_ID).toString();
            log.info("当前用户的id:{}",userid);
            BaseContext.setCurrentId(Long.parseLong(userid));
        }catch (Exception e){
            log.info("令牌校验失败");
        }
        //从redis中获取用户信息(保护用户信息，权限信息等)
//        System.out.println(redisTemplate.opsForValue().get(RedisHeader.userId + userid));
        ObjectMapper objectMapper = new ObjectMapper();
        SecurityUser securityUser = objectMapper.convertValue(redisTemplate.opsForValue().get(RedisHeader.userId + userid), SecurityUser.class);
        if(securityUser==null){
            throw new RuntimeException("用户登录异常");
        }
        Collection<SimpleGrantedAuthority> authorities=new ArrayList<>();
        for(String s:securityUser.getAuthorities()){
            authorities.add(new SimpleGrantedAuthority(s));
        }
        //存入SecurityContextHolder
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(securityUser, null, authorities);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(request,response);
    }
}
